﻿using Game;
using RecipaediaEX.ComponentsExtra;
using System.Collections.Generic;
using TemplatesDatabase;
using ZLinq;
using System;

namespace RecipaediaEX.Implementation {
    public abstract class FormattedRecipe : IRecipe {
        public int ResultValue;

        public int ResultCount;

        public int RemainsValue;

        public int RemainsCount;

        public float RequiredHeatLevel;

        public float RequiredPlayerLevel;

        public string[] Ingredients = new string[36];

        public string Description;

        public string Message;

        public bool LogErrorOnMatchFail = false;

        public virtual int MatchPriority => 0;

        public HashSet<string[]> TransformedIngredients = new();
        
        public ValuesDictionary ExtraValues = new();

        /// <summary>
        /// 在配方表中的显示顺序，DisplayOrder越小，配方越靠前
        /// </summary>
        public int DisplayOrder = 0;
        int IRecipe.DisplayOrder => DisplayOrder;

        public virtual bool Match(IRecipe actual) {
            try {
                if (actual is not FormattedRecipe formattedRecipe) return false;
                return TransformedIngredients.AsValueEnumerable().Any(
                    ingredients => CompareIngredientsArray(ingredients, formattedRecipe.Ingredients)
                );
            }
            catch(Exception e) {
                if (LogErrorOnMatchFail) {
                    Engine.Log.Error("[RecipaediaEX]Formatted Recipe Match Error: " + e);
                }
                return false;
            }
        }
        public virtual bool CompareIngredientsArray(string[]? requiredIngredient, string[]? actualIngredient) {
            if (requiredIngredient == null || actualIngredient == null)
                return requiredIngredient == actualIngredient;

            // 如果长度不同，则直接返回 false
            if (requiredIngredient.Length != actualIngredient.Length)
                return false;

            // 使用 CompareIngredients 比较每个元素
            for (int i = 0; i < requiredIngredient.Length; i++) {
                if (!CompareIngredient(requiredIngredient[i], actualIngredient[i]))
                    return false;
            }

            return true;
        }
        public virtual bool CompareIngredient(string requiredIngredient, string actualIngredient) {
            return CraftingRecipesManager.CompareIngredients(requiredIngredient, actualIngredient);
        }

        public virtual T GetExtraValue<T>(string key, T defaultValue) => ExtraValues.GetValue(key, defaultValue);

        public void SetExtraValue<T>(string key, T value) => ExtraValues.SetValue(key, value);

        public void PreTransformIngredients() {
            TransformedIngredients.Clear();
            for (int i = 0; i < 2; i++) {
                for (int j = -6; j <= 6; j++) {
                    for (int k = -6; k <= 6; k++) {
                        bool flip = i != 0;
                        string[] array = new string[36];
                        if (!OriginalComponentsExtensions.TransformRecipe(array, Ingredients, k, j, flip)) {
                            continue;
                        }
                        TransformedIngredients.Add(array);
                    }
                }
            }
        }
    }
}